package chen.yi.component.code.generator.actuator;

import chen.yi.component.code.generator.config.BaseInfoConfig;
import chen.yi.component.code.generator.constant.TemplateNameConstant;
import chen.yi.component.code.generator.entity.AttributePO;
import chen.yi.component.code.generator.entity.ClassPO;
import chen.yi.component.code.generator.enums.DatabaseTypeMappingEnums;
import chen.yi.component.code.generator.mapper.TableMapper;
import chen.yi.component.code.generator.utils.TemplateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 代码生成执行器
 *
 * @author huat
 **/
@Component
public class CodeActuator extends TemplateUtils {
    private final TableMapper tableMapper;
    private final BaseInfoConfig baseInfoConfig;


    @Autowired
    public CodeActuator(TableMapper tableMapper,BaseInfoConfig baseInfoConfig) {
        this.tableMapper = tableMapper;
        this.baseInfoConfig = baseInfoConfig;
    }

    /**
     * 生成po代码 有父类
     *
     * @param tableName 数据库表名
     * @param clazz     父类
     * @return po模板代码
     */
    public String getEntityCode(String tableName, Class<?> clazz) {
        List<Field> field = getField(clazz);
        List<String> fieldNames = field.stream().map(Field::getName).toList();
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        List<AttributePO> list = classPO.getAttributeList().stream().filter(item -> !fieldNames.contains(item.getAttributeField())).toList();
        classPO.setAttributeList(list);
        classPO.setClassName(getClassName(tableName));
        classPO.setParentPackage(clazz.getPackageName());
        classPO.setParentClass(clazz.getSimpleName());
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }

    /**
     * 生成po代码
     *
     * @param tableName 数据库表名
     * @return po模板代码
     */
    public String getEntityCode(String tableName) {
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        classPO.setClassName(getClassName(tableName));
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }
    /**
     * 生成dto代码 有父类
     *
     * @param tableName 数据库表名
     * @param clazz     父类
     * @return po模板代码
     */
    public String getDTOCode(String tableName, Class<?> clazz) {
        List<Field> field = getField(clazz);
        List<String> fieldNames = field.stream().map(Field::getName).toList();
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        List<AttributePO> list = classPO.getAttributeList().stream().filter(item -> !fieldNames.contains(item.getAttributeField())).toList();
        classPO.setAttributeList(list);
        classPO.setClassName(getClassName(tableName));
        classPO.setParentPackage(clazz.getPackageName());
        classPO.setParentClass(clazz.getSimpleName());
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }

    /**
     * 生成dto代码
     *
     * @param tableName 数据库表名
     * @return po模板代码
     */
    public String getDTOCode(String tableName) {
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        classPO.setClassName(getClassName(tableName));
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }
    /**
     * 生成vo代码 有父类
     *
     * @param tableName 数据库表名
     * @param clazz     父类
     * @return po模板代码
     */
    public String getVOCode(String tableName, Class<?> clazz) {
        List<Field> field = getField(clazz);
        List<String> fieldNames = field.stream().map(Field::getName).toList();
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        List<AttributePO> list = classPO.getAttributeList().stream().filter(item -> !fieldNames.contains(item.getAttributeField())).toList();
        classPO.setAttributeList(list);
        classPO.setClassName(getClassName(tableName));
        classPO.setParentPackage(clazz.getPackageName());
        classPO.setParentClass(clazz.getSimpleName());
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }

    /**
     * 生成vo代码
     *
     * @param tableName 数据库表名
     * @return po模板代码
     */
    public String getVOCode(String tableName) {
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        getAttr(classPO);
        classPO.setClassName(getClassName(tableName));
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        return templateData(TemplateNameConstant.CREATE_PO, classPO);
    }

    /**
     * 生成mapper代码
     * @param tableName
     * @return
     */
    public String getMapperCode(String tableName){
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        classPO.setClassName(getClassName(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setMapperPackage(baseInfoConfig.getMapperPackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_MAPPER, classPO);
    }
    /**
     * 生成service代码
     * @param tableName
     * @return
     */
    public String getServiceCode(String tableName){
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        classPO.setClassName(getClassName(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setMapperPackage(baseInfoConfig.getMapperPackage());
        classPO.setServicePackage(baseInfoConfig.getServicePackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_SERVICE, classPO);
    }
    /**
     * 生成service实现类 代码
     * @param tableName
     * @return
     */
    public String getServiceImplCode(String tableName){
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        classPO.setClassName(getClassName(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setPoPackage(baseInfoConfig.getEntityPackage());
        classPO.setMapperPackage(baseInfoConfig.getMapperPackage());
        classPO.setServicePackage(baseInfoConfig.getServicePackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_SERVICE_IMPL, classPO);
    }
    /**
     * 生成Controller代码
     * @param tableName
     * @return
     */
    public String getControllerCode(String tableName){
        ClassPO classPO = tableMapper.getTableEntityList(tableName);
        tableName=tableName.replaceFirst(baseInfoConfig.getTablePrefix(),"");
        classPO.setClassName(getClassName(tableName));
        classPO.setAuthorName(baseInfoConfig.getAuthorName());
        classPO.setControllerPackage(baseInfoConfig.getControllerPackage());
        classPO.setServicePackage(baseInfoConfig.getServicePackage());
        classPO.setPackageSuffix(getPackageNameSuffix(tableName));
        return templateData(TemplateNameConstant.CREATE_CONTROLLER, classPO);
    }
    /**
     * 获取包名后缀
     * @param tableName 表名
     * @return 包名后缀
     */
    private static   String getPackageNameSuffix(String tableName) {
        tableName=tableName.toLowerCase();
        String[] s = tableName.split("_");
        return s[0];
    }

    /**
     * 获取类名
     *
     * @param tableName 表名
     * @return 类名
     */
    private static String getClassName(String tableName) {
        StringBuilder sb = new StringBuilder();
        //将表名转为大写
        tableName = tableName.toUpperCase();
        String[] tableNameArray = tableName.split("_");
        for (String s : tableNameArray) {
            String classNamePrefix = s.substring(0, 1);
            String classNameSuffix = s.substring(1).toLowerCase();
            sb.append(classNamePrefix).append(classNameSuffix);
        }
        return sb.toString();
    }

    /**
     * 转换属性类型以及生成属性名
     *
     * @param classPO 类对象
     */
    private static void getAttr(ClassPO classPO) {
        classPO.getAttributeList().forEach(attributePO -> {
            String attributeType = attributePO.getAttributeType();
            attributeType = DatabaseTypeMappingEnums.getJavaTypeByDatabaseType(attributeType);
            attributePO.setAttributeType(attributeType);
            String attributeField = attributePO.getColumnName();
            attributePO.setAttributeField(getAttrName(attributeField));
        });
    }

    /**
     * 获取属性名
     *
     * @param attrName 属性名
     * @return 类名
     */
    private static String getAttrName(String attrName) {
        StringBuilder sb = new StringBuilder();
        //将表名转为小写
        attrName = attrName.toLowerCase();
        String[] attrNameArray = attrName.split("_");
        if (attrNameArray.length < 2) {
            return attrName;
        }
        sb.append(attrNameArray[0]);
        for (int i = 1; i < attrNameArray.length; i++) {
            String classNamePrefix = attrNameArray[i].substring(0, 1).toUpperCase();
            String classNameSuffix = attrNameArray[i].substring(1);
            sb.append(classNamePrefix).append(classNameSuffix);
        }
        return sb.toString();
    }

    /**
     * 获取对象属性值
     */
    public static List<Field> getField(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null) {
            fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
            clazz = clazz.getSuperclass(); // 递归处理父类
        }
        return fields;

    }
}
